﻿using Gasgoo.ShareLibrary.Framework.iQueueProvider;
using Gasgoo.ShareLibrary.Framework.ServiceDefine;
using Orleans;
using Orleans.Runtime;
using Orleans.Versions.Compatibility;
using Orleans.Versions.Selector;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Gasgoo.ShareLibrary.Framework
{
    public interface IClusterService
    {
        T GetInterface<T>();
        T GetService<T>() where T : GasgooService;
        T GetService<T>(Guid primaryKey) where T : GasgooServiceWithGuidKey;
        T GetService<T>(long primaryKey) where T : GasgooServiceWithIntegerKey;
        T GetService<T>(string primaryKey) where T : GasgooServiceWithStringKey;
        T GetService<T>(long primaryKey1, string primaryKey2) where T : GasgooServiceWithIntegerCompoundKey;
        T GetService<T>(Guid primaryKey1, string primaryKey2) where T : GasgooServiceWithGuidCompoundKey;
        IManagement GetManagementer();
        Task StopAsync();
        IQueueProvider GetQueueProvider(string name);
    }

    public interface IManagement : IManagementGrain
    {

    }

    public class ManagementService : IManagement
    {
        IManagementGrain managementGrain;
        public ManagementService(IManagementGrain managementGrain) { this.managementGrain = managementGrain; }
        public Task ForceActivationCollection(SiloAddress[] hostsIds, TimeSpan ageLimit) => this.managementGrain.ForceActivationCollection(hostsIds, ageLimit);

        public Task ForceActivationCollection(TimeSpan ageLimit) => this.managementGrain.ForceActivationCollection(ageLimit);

        public Task ForceGarbageCollection(SiloAddress[] hostsIds) => this.managementGrain.ForceGarbageCollection(hostsIds);

        public Task ForceRuntimeStatisticsCollection(SiloAddress[] siloAddresses) => this.managementGrain.ForceRuntimeStatisticsCollection(siloAddresses);

        public ValueTask<SiloAddress> GetActivationAddress(IAddressable reference) => this.managementGrain.GetActivationAddress(reference);

        public Task<string[]> GetActiveGrainTypes(SiloAddress[] hostsIds = null) => this.managementGrain.GetActiveGrainTypes(hostsIds);

        public Task<DetailedGrainStatistic[]> GetDetailedGrainStatistics(string[] types = null, SiloAddress[] hostsIds = null) => this.managementGrain.GetDetailedGrainStatistics(types, hostsIds);

        public Task<MembershipEntry[]> GetDetailedHosts(bool onlyActive = false) => this.managementGrain.GetDetailedHosts(onlyActive);

        public Task<int> GetGrainActivationCount(GrainReference grainReference) => this.managementGrain.GetGrainActivationCount(grainReference);

        public Task<Dictionary<SiloAddress, SiloStatus>> GetHosts(bool onlyActive = false) => this.managementGrain.GetHosts(onlyActive);

        public Task<SiloRuntimeStatistics[]> GetRuntimeStatistics(SiloAddress[] hostsIds) => this.managementGrain.GetRuntimeStatistics(hostsIds);

        public Task<SimpleGrainStatistic[]> GetSimpleGrainStatistics(SiloAddress[] hostsIds) => this.managementGrain.GetSimpleGrainStatistics(hostsIds);

        public Task<SimpleGrainStatistic[]> GetSimpleGrainStatistics() => this.managementGrain.GetSimpleGrainStatistics();

        public Task<int> GetTotalActivationCount() => this.managementGrain.GetTotalActivationCount();

        public Task<object[]> SendControlCommandToProvider(string providerTypeFullName, string providerName, int command, object arg = null)
            => this.managementGrain.SendControlCommandToProvider(providerTypeFullName, providerName, command, arg);

        public Task SetCompatibilityStrategy(CompatibilityStrategy strategy) => this.managementGrain.SetCompatibilityStrategy(strategy);

        public Task SetCompatibilityStrategy(int interfaceId, CompatibilityStrategy strategy) => this.managementGrain.SetCompatibilityStrategy(interfaceId, strategy);

        public Task SetSelectorStrategy(VersionSelectorStrategy strategy) => this.managementGrain.SetSelectorStrategy(strategy);

        public Task SetSelectorStrategy(int interfaceId, VersionSelectorStrategy strategy) => this.managementGrain.SetSelectorStrategy(interfaceId, strategy);
    }
}
